#define ANKERL_NANOBENCH_IMPLEMENT

#include <cib/cib.hpp>
#include <match/ops.hpp>
#include <msg/callback.hpp>
#include <msg/field.hpp>
#include <msg/indexed_service.hpp>
#include <msg/message.hpp>
#include <msg/service.hpp>

#include <stdx/utility.hpp>

#include <array>

#include <nanobench.h>

using namespace msg;

using big_f = field<"big", std::uint32_t>::located<at{0_dw, 31_msb, 0_lsb}>;
using med_f = field<"med", std::uint32_t>::located<at{1_dw, 15_msb, 0_lsb}>;
using small_a_f =
    field<"small_a", std::uint32_t>::located<at{1_dw, 23_msb, 16_lsb}>;
using small_b_f =
    field<"small_b", std::uint32_t>::located<at{1_dw, 31_msb, 24_lsb}>;
using flag_1_f = field<"flag_1", bool>::located<at{2_dw, 0_msb, 0_lsb}>;
using flag_2_f = field<"flag_2", bool>::located<at{2_dw, 1_msb, 1_lsb}>;
using flag_3_f = field<"flag_3", bool>::located<at{2_dw, 2_msb, 2_lsb}>;

using msg_defn = message<"bench_msg", big_f, med_f, small_a_f, small_b_f,
                         flag_1_f, flag_2_f, flag_3_f>;

using msg_t = owning<msg_defn>;

struct test_indexed_service
    : indexed_service<index_spec<big_f, med_f, small_a_f>, msg_t> {};
struct test_service : service<msg_t> {};

uint64_t cb_count{};
uint64_t volatile *cb_count_ptr = &cb_count;

template <uint32_t B, uint32_t M, uint32_t S>
constexpr auto cb = msg::callback<"callback", msg_defn>(
    "big"_f.in<B> and "med"_f.in<M> and "small_a"_f.in<S>,
    [](auto) { (*cb_count_ptr) = 0; });

template <typename T> struct test_project {
    constexpr static auto config = cib::config(
        cib::exports<T>,
        cib::extend<T>(
            cb<7408991, 1529, 4>, cb<25790222, 1603, 10>, cb<686755, 764, 7>,
            cb<41609698, 2178, 26>, cb<52281510, 249, 5>,
            cb<31889573, 2946, 14>, cb<3221205, 226, 5>, cb<25993058, 1721, 4>,
            cb<100432494, 4815, 8>, cb<60581460, 94, 8>, cb<49293955, 604, 1>,
            cb<31889573, 94, 10>, cb<89547232, 1028, 5>, cb<11651136, 411, 2>,
            cb<8872200, 1392, 26>, cb<52281510, 861, 10>, cb<7203140, 1721, 9>,
            cb<12158142, 1011, 9>, cb<61707443, 252, 0>, cb<29897602, 369, 26>,
            cb<37597100, 174, 2>, cb<48754189, 884, 14>, cb<57295152, 1011, 10>,
            cb<11501494, 1028, 10>, cb<1582483, 139, 1>, cb<25102716, 411, 3>,
            cb<18420386, 1721, 1>, cb<8872200, 3918, 0>, cb<37597100, 1153, 4>,
            cb<14399730, 3852, 5>, cb<3346740, 1721, 10>, cb<89547232, 764, 5>,
            cb<31972723, 3138, 2>, cb<11651136, 3852, 4>, cb<18420386, 2946, 8>,
            cb<61707443, 1011, 26>, cb<12158142, 1028, 2>,
            cb<13467223, 1028, 2>, cb<1895786, 5, 0>, cb<4251912, 3918, 5>,
            cb<31889573, 604, 1>, cb<25993058, 1153, 5>, cb<48754189, 1028, 10>,
            cb<1146788, 1603, 1>, cb<31889573, 428, 18>, cb<34849760, 345, 8>,
            cb<7052035, 988, 2>, cb<78542133, 428, 4>, cb<28690868, 4815, 26>,
            cb<4251912, 861, 3>, cb<127101820, 225, 4>, cb<6656070, 1071, 4>,
            cb<2410641, 2179, 2>, cb<2255862, 338, 8>, cb<3221205, 2604, 8>,
            cb<686755, 433, 2>, cb<2872476, 369, 0>, cb<16348301, 411, 10>,
            cb<45450308, 651, 0>, cb<13019260, 428, 1>, cb<31972723, 2178, 0>,
            cb<60581460, 5, 4>, cb<57295152, 226, 2>, cb<19954040, 1096, 3>,
            cb<5060444, 988, 10>, cb<57295152, 1314, 4>, cb<8624366, 1028, 5>,
            cb<14348655, 249, 18>, cb<56778125, 531, 0>, cb<35154099, 3588, 1>,
            cb<78542133, 369, 2>, cb<16925693, 252, 5>, cb<89547232, 2179, 14>,
            cb<11651136, 1579, 3>, cb<8624366, 676, 9>, cb<7203140, 243, 5>,
            cb<61707443, 764, 14>, cb<2255862, 338, 2>, cb<13019260, 3138, 3>,
            cb<4747399, 1153, 14>, cb<4308812, 1392, 14>, cb<18420386, 1392, 5>,
            cb<16348301, 433, 2>, cb<3752116, 1314, 5>, cb<57295152, 226, 4>,
            cb<3346740, 411, 26>, cb<31889573, 1603, 26>, cb<19954040, 988, 1>,
            cb<13393613, 651, 4>, cb<100432494, 94, 26>, cb<32984781, 94, 2>,
            cb<26301699, 1096, 10>, cb<11501494, 174, 2>, cb<36923972, 411, 18>,
            cb<29897602, 988, 10>, cb<37597100, 604, 7>, cb<156064102, 1071, 2>,
            cb<21054211, 3918, 10>, cb<62294716, 1721, 10>,
            cb<13220408, 2179, 0>, cb<21054211, 100, 4>, cb<1582483, 764, 26>,
            cb<13393613, 338, 1>, cb<11924917, 1579, 3>, cb<8624366, 411, 10>,
            cb<8872200, 139, 10>, cb<12158142, 4815, 10>, cb<48754189, 249, 10>,
            cb<17198460, 884, 26>, cb<30549348, 225, 0>, cb<8749337, 4677, 14>,
            cb<16925693, 4815, 2>, cb<89547232, 277, 1>, cb<686755, 3852, 4>,
            cb<686755, 411, 8>, cb<16828919, 433, 0>, cb<1146788, 2604, 7>,
            cb<62626451, 1153, 14>, cb<6683087, 676, 3>, cb<49293955, 1721, 0>,
            cb<1146788, 1529, 18>, cb<2410641, 861, 2>, cb<45450308, 503, 10>,
            cb<25102716, 2179, 5>, cb<14399730, 369, 10>, cb<16052435, 225, 2>,
            cb<29897602, 1721, 0>, cb<6656070, 225, 7>, cb<8749337, 1153, 7>,
            cb<11501494, 252, 26>, cb<11651136, 139, 8>, cb<60581460, 1603, 4>,
            cb<14348655, 604, 14>, cb<2555344, 338, 4>, cb<16828919, 748, 5>,
            cb<25790222, 243, 7>, cb<62294716, 861, 3>, cb<89547232, 4815, 26>,
            cb<25993058, 604, 18>, cb<29897602, 433, 3>, cb<156064102, 531, 10>,
            cb<37597100, 428, 0>, cb<127101820, 249, 5>, cb<7011312, 3138, 3>,
            cb<7011312, 100, 5>, cb<13393613, 226, 2>, cb<4747399, 604, 14>,
            cb<26301699, 139, 4>, cb<3752116, 988, 3>, cb<73625537, 225, 5>,
            cb<13019260, 861, 14>, cb<14399730, 651, 10>, cb<41609698, 764, 2>,
            cb<18420386, 433, 4>, cb<48754189, 1579, 2>, cb<18420386, 2946, 1>,
            cb<31889573, 1028, 4>, cb<17198460, 764, 9>, cb<6375193, 174, 3>,
            cb<17118917, 2946, 4>, cb<48754189, 2178, 2>, cb<6656070, 604, 2>,
            cb<57295152, 4815, 2>, cb<52281510, 1028, 2>, cb<3752116, 3588, 10>,
            cb<773601, 94, 14>, cb<16828919, 1314, 3>, cb<25224297, 277, 5>,
            cb<1929157, 100, 0>, cb<7203140, 1721, 18>, cb<7052035, 428, 0>,
            cb<18420386, 226, 7>, cb<4308812, 369, 10>, cb<11488991, 1392, 8>,
            cb<773601, 225, 5>, cb<36923972, 249, 5>, cb<2255862, 411, 1>,
            cb<127101820, 503, 3>, cb<25993058, 861, 4>, cb<36923972, 1529, 4>,
            cb<60581460, 174, 5>, cb<35808318, 988, 18>, cb<20878407, 531, 9>,
            cb<6683087, 226, 26>, cb<2255862, 3588, 4>, cb<16828919, 1011, 10>,
            cb<29557916, 676, 4>, cb<1582483, 988, 2>, cb<2255862, 338, 0>,
            cb<7052035, 1028, 2>, cb<52281510, 5, 0>, cb<1710651, 100, 0>,
            cb<3752116, 4815, 4>, cb<78542133, 2604, 10>, cb<13467223, 3852, 1>,
            cb<3221205, 411, 10>, cb<31972723, 3588, 3>, cb<89547232, 748, 26>,
            cb<6656070, 3852, 2>, cb<14399730, 884, 5>, cb<25102716, 345, 0>,
            cb<11924917, 1529, 2>, cb<57295152, 2178, 18>, cb<35154099, 433, 2>,
            cb<21054211, 5, 14>, cb<29873573, 2179, 3>, cb<773601, 1603, 10>,
            cb<25790222, 5, 2>, cb<6656070, 100, 10>, cb<7408991, 1011, 8>,
            cb<5060444, 604, 3>, cb<2255862, 2179, 10>, cb<25224297, 338, 3>,
            cb<13467223, 338, 8>, cb<3752116, 651, 2>, cb<19954040, 604, 8>,
            cb<156064102, 369, 2>, cb<1929157, 1579, 10>, cb<18420386, 861, 2>,
            cb<29557916, 252, 9>, cb<25790222, 4677, 8>, cb<8749337, 1392, 3>,
            cb<7203140, 20, 10>, cb<7408991, 988, 18>, cb<16348301, 2530, 10>,
            cb<13019260, 1096, 10>, cb<25102716, 3852, 4>,
            cb<25993058, 345, 14>, cb<1710651, 861, 8>, cb<52281510, 3138, 10>,
            cb<45450308, 1096, 4>, cb<8624366, 676, 0>, cb<2872476, 1392, 26>,
            cb<11488991, 1603, 10>, cb<13220408, 1096, 5>,
            cb<31252036, 884, 14>, cb<8624366, 226, 2>, cb<842387, 1153, 18>,
            cb<6375193, 1314, 0>, cb<13019260, 2604, 14>, cb<13220408, 1071, 4>,
            cb<56228327, 243, 4>, cb<53124307, 2604, 5>, cb<21054211, 861, 1>,
            cb<20878407, 1028, 5>, cb<24553653, 604, 3>, cb<73625537, 531, 2>,
            cb<7408991, 3918, 2>, cb<3832590, 604, 1>, cb<14399730, 433, 8>,
            cb<25993058, 4677, 4>, cb<13393613, 249, 10>, cb<48754189, 604, 4>,
            cb<11685653, 2946, 4>, cb<8872200, 2946, 5>,
            cb<3832590, 2946, 18>));
};

template <uint32_t B, uint32_t M, uint32_t S>
constexpr auto m = msg_t{"big"_field = B, "med"_field = M, "small_a"_field = S};

template <typename T> void bench_handler() {
    cib::nexus<test_project<T>> test_nexus{};
    test_nexus.init();

    auto msgs = std::array{
        m<7408991, 1529, 4>,   m<25790222, 1603, 10>, m<686755, 764, 7>,
        m<41609698, 2178, 26>, m<52281510, 249, 5>,   m<31889573, 2946, 14>,
        m<3221205, 226, 5>,    m<25993058, 1721, 4>,  m<100432494, 4815, 8>,
        m<60581460, 94, 8>,    m<49293955, 604, 1>,   m<31889573, 94, 10>,
        m<89547232, 1028, 5>,  m<11651136, 411, 2>,   m<8872200, 1392, 26>,
        m<52281510, 861, 10>,  m<7203140, 1721, 9>,   m<12158142, 1011, 9>,
        m<61707443, 252, 0>,   m<29897602, 369, 26>,  m<37597100, 174, 2>,
        m<48754189, 884, 14>,  m<57295152, 1011, 10>, m<11501494, 1028, 10>,
        m<1582483, 139, 1>,    m<25102716, 411, 3>,   m<18420386, 1721, 1>,
        m<8872200, 3918, 0>,   m<37597100, 1153, 4>,  m<14399730, 3852, 5>,
        m<3346740, 1721, 10>,  m<89547232, 764, 5>,   m<31972723, 3138, 2>,
        m<11651136, 3852, 4>,  m<18420386, 2946, 8>,  m<61707443, 1011, 26>,
        m<12158142, 1028, 2>,  m<13467223, 1028, 2>,  m<1895786, 5, 0>,
        m<4251912, 3918, 5>,   m<31889573, 604, 1>,   m<25993058, 1153, 5>,
        m<48754189, 1028, 10>, m<1146788, 1603, 1>,   m<31889573, 428, 18>,
        m<34849760, 345, 8>,   m<7052035, 988, 2>,    m<78542133, 428, 4>,
        m<28690868, 4815, 26>, m<4251912, 861, 3>,    m<127101820, 225, 4>,
        m<6656070, 1071, 4>,   m<2410641, 2179, 2>,   m<2255862, 338, 8>,
        m<3221205, 2604, 8>,   m<686755, 433, 2>,     m<2872476, 369, 0>,
        m<16348301, 411, 10>,  m<45450308, 651, 0>,   m<13019260, 428, 1>,
        m<31972723, 2178, 0>,  m<60581460, 5, 4>,     m<57295152, 226, 2>,
        m<19954040, 1096, 3>,  m<5060444, 988, 10>,   m<57295152, 1314, 4>,
        m<8624366, 1028, 5>,   m<14348655, 249, 18>,  m<56778125, 531, 0>,
        m<35154099, 3588, 1>,  m<78542133, 369, 2>,   m<16925693, 252, 5>,
        m<89547232, 2179, 14>, m<11651136, 1579, 3>,  m<8624366, 676, 9>,
        m<7203140, 243, 5>,    m<61707443, 764, 14>,  m<2255862, 338, 2>,
        m<13019260, 3138, 3>,  m<4747399, 1153, 14>,  m<4308812, 1392, 14>,
        m<18420386, 1392, 5>,  m<16348301, 433, 2>,   m<3752116, 1314, 5>,
        m<57295152, 226, 4>,   m<3346740, 411, 26>,   m<31889573, 1603, 26>,
        m<19954040, 988, 1>,   m<13393613, 651, 4>,   m<100432494, 94, 26>,
        m<32984781, 94, 2>,    m<26301699, 1096, 10>, m<11501494, 174, 2>,
        m<36923972, 411, 18>,  m<29897602, 988, 10>,  m<37597100, 604, 7>,
        m<156064102, 1071, 2>, m<21054211, 3918, 10>, m<62294716, 1721, 10>,
        m<13220408, 2179, 0>,  m<21054211, 100, 4>,   m<1582483, 764, 26>,
        m<13393613, 338, 1>,   m<11924917, 1579, 3>,  m<8624366, 411, 10>,
        m<8872200, 139, 10>,   m<12158142, 4815, 10>, m<48754189, 249, 10>,
        m<17198460, 884, 26>,  m<30549348, 225, 0>,   m<8749337, 4677, 14>,
        m<16925693, 4815, 2>,  m<89547232, 277, 1>,   m<686755, 3852, 4>,
        m<686755, 411, 8>,     m<16828919, 433, 0>,   m<1146788, 2604, 7>,
        m<62626451, 1153, 14>, m<6683087, 676, 3>,    m<49293955, 1721, 0>,
        m<1146788, 1529, 18>,  m<2410641, 861, 2>,    m<45450308, 503, 10>,
        m<25102716, 2179, 5>,  m<14399730, 369, 10>,  m<16052435, 225, 2>,
        m<29897602, 1721, 0>,  m<6656070, 225, 7>,    m<8749337, 1153, 7>,
        m<11501494, 252, 26>,  m<11651136, 139, 8>,   m<60581460, 1603, 4>,
        m<14348655, 604, 14>,  m<2555344, 338, 4>,    m<16828919, 748, 5>,
        m<25790222, 243, 7>,   m<62294716, 861, 3>,   m<89547232, 4815, 26>,
        m<25993058, 604, 18>,  m<29897602, 433, 3>,   m<156064102, 531, 10>,
        m<37597100, 428, 0>,   m<127101820, 249, 5>,  m<7011312, 3138, 3>,
        m<7011312, 100, 5>,    m<13393613, 226, 2>,   m<4747399, 604, 14>,
        m<26301699, 139, 4>,   m<3752116, 988, 3>,    m<73625537, 225, 5>,
        m<13019260, 861, 14>,  m<14399730, 651, 10>,  m<41609698, 764, 2>,
        m<18420386, 433, 4>,   m<48754189, 1579, 2>,  m<18420386, 2946, 1>,
        m<31889573, 1028, 4>,  m<17198460, 764, 9>,   m<6375193, 174, 3>,
        m<17118917, 2946, 4>,  m<48754189, 2178, 2>,  m<6656070, 604, 2>,
        m<57295152, 4815, 2>,  m<52281510, 1028, 2>,  m<3752116, 3588, 10>,
        m<773601, 94, 14>,     m<16828919, 1314, 3>,  m<25224297, 277, 5>,
        m<1929157, 100, 0>,    m<7203140, 1721, 18>,  m<7052035, 428, 0>,
        m<18420386, 226, 7>,   m<4308812, 369, 10>,   m<11488991, 1392, 8>,
        m<773601, 225, 5>,     m<36923972, 249, 5>,   m<2255862, 411, 1>,
        m<127101820, 503, 3>,  m<25993058, 861, 4>,   m<36923972, 1529, 4>,
        m<60581460, 174, 5>,   m<35808318, 988, 18>,  m<20878407, 531, 9>,
        m<6683087, 226, 26>,   m<2255862, 3588, 4>,   m<16828919, 1011, 10>,
        m<29557916, 676, 4>,   m<1582483, 988, 2>,    m<2255862, 338, 0>,
        m<7052035, 1028, 2>,   m<52281510, 5, 0>,     m<1710651, 100, 0>,
        m<3752116, 4815, 4>,   m<78542133, 2604, 10>, m<13467223, 3852, 1>,
        m<3221205, 411, 10>,   m<31972723, 3588, 3>,  m<89547232, 748, 26>,
        m<6656070, 3852, 2>,   m<14399730, 884, 5>,   m<25102716, 345, 0>,
        m<11924917, 1529, 2>,  m<57295152, 2178, 18>, m<35154099, 433, 2>,
        m<21054211, 5, 14>,    m<29873573, 2179, 3>,  m<773601, 1603, 10>,
        m<25790222, 5, 2>,     m<6656070, 100, 10>,   m<7408991, 1011, 8>,
        m<5060444, 604, 3>,    m<2255862, 2179, 10>,  m<25224297, 338, 3>,
        m<13467223, 338, 8>,   m<3752116, 651, 2>,    m<19954040, 604, 8>,
        m<156064102, 369, 2>,  m<1929157, 1579, 10>,  m<18420386, 861, 2>,
        m<29557916, 252, 9>,   m<25790222, 4677, 8>,  m<8749337, 1392, 3>,
        m<7203140, 20, 10>,    m<7408991, 988, 18>,   m<16348301, 2530, 10>,
        m<13019260, 1096, 10>, m<25102716, 3852, 4>,  m<25993058, 345, 14>,
        m<1710651, 861, 8>,    m<52281510, 3138, 10>, m<45450308, 1096, 4>,
        m<8624366, 676, 0>,    m<2872476, 1392, 26>,  m<11488991, 1603, 10>,
        m<13220408, 1096, 5>,  m<31252036, 884, 14>,  m<8624366, 226, 2>,
        m<842387, 1153, 18>,   m<6375193, 1314, 0>,   m<13019260, 2604, 14>,
        m<13220408, 1071, 4>,  m<56228327, 243, 4>,   m<53124307, 2604, 5>,
        m<21054211, 861, 1>,   m<20878407, 1028, 5>,  m<24553653, 604, 3>,
        m<73625537, 531, 2>,   m<7408991, 3918, 2>,   m<3832590, 604, 1>,
        m<14399730, 433, 8>,   m<25993058, 4677, 4>,  m<13393613, 249, 10>,
        m<48754189, 604, 4>,   m<11685653, 2946, 4>,  m<8872200, 2946, 5>,
        m<3832590, 2946, 18>,
    };

    auto i = std::size_t{};
    ankerl::nanobench::Bench().minEpochIterations(2000000).run("msgs", [&] {
        cib::service<T>->handle(msgs[i]);
        i = (i + 1) % msgs.size();
    });
}

int main() {
    bench_handler<test_indexed_service>();
    bench_handler<test_service>();
}
